﻿using UnityEngine;
using System.Collections.Generic;
using System;

public class PathNode : IComparable<PathNode>
{
    public int G;
    public int H;
    public int F
    {
        get
        {
            return G + H;
        }
    }

    public PathNode Parent;
    public Vector2 Position;

    public PathNode(Vector2 pos)
    {
        this.Position = pos;
        this.Parent = null;
        this.G = 0;
        this.H = 0;
    }

    public override string ToString()
    {
        return Position.ToString();
    }

    #region IComparable<PathNode> Members

    public int CompareTo(PathNode other)
    {
        return F - other.F;
    }

    #endregion
}

public class AStar
    {
        //获得G值
        private int G(int parent)
        {
            int d = 10;
            return d + parent;
        }
        
        //获得H值
        private int H(int x, int y, Vector2 end)
        {
            return (Math.Abs(x - (int)end.x) + Math.Abs(y - (int)end.y)) * 10;
        }
        
        //开启列表
        private List<PathNode> unLockList = new List<PathNode>();
        //关闭列表
        private List<PathNode> lockList = new List<PathNode> ();
        //最终路径
        public List<PathNode> path = new List<PathNode>();
        //遍历点声明
        private int[][] delta = new int[][]{
            new int[]{0,1},
            new int[]{0,-1},
            new int[]{1,0},
            new int[]{-1,0}
        };
        ////起始点
        //public Vector2 Start { get; set; }
        ////结束点
        //public Vector2 End { get; set; }

        //寻找路径，返回最终路径
        public List<PathNode> FindPath(Vector2 _start, Vector2 _end)
        {
            unLockList.Clear();
            lockList.Clear();
            path.Clear();
            doFindPath(_start, _end);
            path.Reverse();
            return path;
        }

        private void doFindPath(Vector2 _start, Vector2 _end)
        {
            PathNode start = new PathNode(_start);
            PathNode cur = start;
            while (true)
            {
                if (!lockList.Contains(cur))
                    lockList.Add(cur);

                for (int i = 0; i < delta.Length; i++)
                {
                    Vector2 newp = new Vector2(cur.Position.x + delta[i][0],
                        cur.Position.y + delta[i][1]);
                    //PathNode node = new PathNode(newp);
                    if (GameManager.gamemanager.lGrid[(int)newp.x][(int)newp.y].isDead)
                        continue;
                    //if (lockList.Contains(node))
                    //    continue;
                    bool isContain=false;
                    foreach(PathNode p in lockList)
                    {
                        if(p.Position==newp)
                        {
                            isContain=true;
                            break;
                        }
                    }
                    if(isContain)
                        continue;
                    if (isPointInUnlockList(newp))
                    {
                        PathNode ulnode = __pn;
                        int newg = G(cur.G);
                        if (newg < ulnode.G)
                        {
                            ulnode.Parent = cur;
                            ulnode.G = newg;
                        }
                        continue;
                    }
                    PathNode newpn = new PathNode(newp);
                    newpn.G = G(cur.G);
                    newpn.H = H((int)newp.x, (int)newp.y, _end);
                    newpn.Parent = cur;
                    unLockList.Add(newpn);
                }
                if (unLockList.Count == 0)
                    break;
                unLockList.Sort();
                cur = unLockList[0];
                unLockList.Remove(cur);
                
                if (cur.Position.Equals(_end))
                {
                    while (cur != null)
                    {
                        path.Add(cur);
                        cur = cur.Parent;
                    }
                    break;
                }
            }
        }

        private PathNode __pn;

        private bool isPointInUnlockList(Vector2 src)
        {
            __pn = null;
            foreach (PathNode item in unLockList)
            {
                if (item.Position.Equals(src))
                {
                    __pn = item;
                    return true;
                }

            }
            return false;
        }

        //private bool canWalkOnIt(Vector2 node)
        //{
        //    if (node.x < 0 || node.y < 0)
        //        return false;
        //    if (node.x > Width - 1 || node.y > Height - 1)
        //        return false;
        //    return GetNodeValue(node.X, node.Y) >= 0;
        //}
    }

